/**
*    This file is part of Basic Service.
*
*    Basic Service is free software: you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    Basic Service is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with Basic Service (See GPL.txt).  If not, see <http://www.gnu.org/licenses/>.
*    
* 	If needed the author is Amir Zucker and can be reached at amirzucker1@gmail.com or amirzucker.wordpress.com
*/
// NOTE THERE IS CODE INCLUDED WHICH IS UNDER BSD LICENSE, READ THE EMBEDDED LICENSE CAREFULLY WHERE APPLICABLE

var MENU_ITEMS = {
		'HOME' : 	['home', 'homeMItem'],
		'ADMIN' : 	['admin', 'adminMItem'],
		'CONTACT' : ['contact', 'contactMItem'],
		'ABOUT' : 	['about', 'aboutMItem'],
}
var Text = {
		"messages.dialog.dialogInvalidFieldLength" : "",
		"messages.dialog.dialogInvalidEmailField" : "",
		"messages.dialog.dialogInvalidPasswordField": "",
		"dialog.dialogField_Name": "",
		"dialog.dialogField_Email": "",
		"dialog.dialogField_Password": "",
		"dialog.dialogField_ValidationKey": "",

		"dialog.dialogField_CurrentPassword": "",
		"dialog.dialogField_ConfirmPassword": "",
		
		"dialog.cancel": "",
		"messages.dialog.registrationDialogHeader": "",
		"messages.dialog.registrationDialogAcceptButton": "",
		"messages.dialog.registrationDialogInitialMessage": "",
		"messages.dialog.loginDialogAcceptButton": "",
		"messages.dialog.loginDialogHeader": "",
		"messages.dialog.loginDialogInitialMessage": "",
		"messages.dialog.resendConfirmationDialogAcceptButton": "",
		"messages.dialog.resendConfirmationDialogHeader": "",
		"messages.dialog.resendConfirmationDialogInitialMessage": "",
		"messages.dialog.resendConfirmationLink": "",
		"messages.dialog.sendResetPasswordEmailDialogAcceptButton": "",
		"messages.dialog.sendResetPasswordEmailDialogHeader": "",
		"messages.dialog.sendResetPasswordEmailDialogInitialMessage": "",
		"messages.dialog.sendResetPasswordEmailLink": "",

		"messages.sendResetPasswordEmail.successHeader": "",
		"messages.sendResetPasswordEmail.successMessage": "",
		"messages.resendConfirmation.successHeader": "",
		"messages.resendConfirmation.successMessage": "",
		"messages.registration.successHeader": "",
		"messages.registration.successMessage": "",

		"messages.logout.error.notLoggedIn.Header": "",
		"messages.logout.error.notLoggedIn.Message": "",
		"messages.logout.error.unknown.Header": "",
		"messages.logout.error.unknown.Message": "",
		
		"messages.changePassword.successHeader": "",
		"messages.changePassword.successMessage": "",
		"messages.dialog.changePasswordDialogHeader": "",
		"messages.dialog.changePasswordDialogAcceptButton": "",
		"messages.dialog.changePasswordDialogInitialMessage": "",
		"messages.resetPassword.successHeader": "",
		"messages.resetPassword.successMessage": "",
		"messages.dialog.resetPasswordDialogHeader": "",
		"messages.dialog.resetPasswordDialogAcceptButton": "",
		"messages.dialog.resetPasswordDialogInitialMessage": "",
		"messages.dialog.messageDialogOkButton": "",
		
		"messages.error.invalidCredentials": "",
		"messages.error.internalServerError": "",
		"messages.error.emailNotFound": "",
		"messages.error.invalidKey": "",
		
		"button.text.login": "",
		"button.text.logout": "",

		"messages.error.login.emailVerificationRequired": "",
		"messages.error.registration.userExistsFailure": "",
		"messages.error.resendConfirmation.emailAlreadyVerified": "",
}

function onPageLoad() {
	bindAjaxCSRFsetup();
	fetchMessagePack();
	initializeMenus();
}
function bindAjaxCSRFsetup() {
	function csrfSafeMethod(method) {
	    // these HTTP methods do not require CSRF protection
	    return (/^(get|head|options|trace)$/.test(method));
	}
	$.ajaxSetup({
	    crossDomain: false, // obviates need for sameOrigin test
	    beforeSend: function(xhr, settings) {
	        if (!csrfSafeMethod(settings.type.toLowerCase())) {
	        	csrf_token = getRandomCSRFToken();
        		xhr.setRequestHeader(Constants.CSRF_TRANSPORT_NAME, csrf_token);
        		setCookie(Constants.CSRF_TRANSPORT_NAME, csrf_token);
	        }
	        if(settings.type.toLowerCase() === "put") {
	        	xhr.setRequestHeader("Content-Length", settings.data.length);
	        	xhr.setRequestHeader("Connection", "close");
	        }
	    }
	});
}
function internalTestServerStatus() {
	$.ajax({
		url: '/api/general/test',
		type: 'GET',
		dataType: 'json',
		data: {},
		success: function(response) { 
			dataLoadedSuccessfully();
		},
		error: function(response) { 
			dataLoadIssuesEncountered();
			setTimeout("internalTestServerStatus()", 10000);
		} 
	});
}
function initializeMenus() {
	for (menu in MENU_ITEMS) {
		if (menu == ACTIVE_MENU_ITEM) {
			makeActiveItem(document.getElementById(MENU_ITEMS[menu][1]));
		} else {
			showNormalMenuStyle(document.getElementById(MENU_ITEMS[menu][1]));
		}
	}
	setVisibility('div#menuItems', true);	
}
function fetchMessagePack() {
	$.ajax({
		url: '/api/general/text/',
		type: 'POST',
		dataType: 'json',
		contentType: "application/json;charset=UTF-8",
		data: JSON.stringify(Text),
		success: function(response) { 
			$.each(response, function(key,val){
				Text[key]=val;
			});
			getUserData();
		},
	    error: function(response) { 
			setTimeout("fetchMessagePack()", 2000);
	    }
	});	
}
function getUserData() {
	$.ajax({
		url: '/api/users/',
		type: 'GET',
		dataType: 'json',
		contentType: "application/json;charset=UTF-8",
		data: {},
		success: function(response) { 
			doOnPageReadyActions();
			setUserLoggedInState();
		},
		error: function(response) { 
			if (response.status == 404) {
				doOnPageReadyActions();
				setUserLoggedOutState();
			} else {
				setTimeout("getUserData()", 2000);
			}
		}
	});	
}
function doOnPageReadyActions() {
	setupDialogParams();
	ActivateDialogButtons();
	pageLoadCustomActions();
}
function changeImageState(buttonId, isOn) {
	var currentSrc = document.getElementById(buttonId).src;
	var imageNameClean = currentSrc.substring(0 ,currentSrc.indexOf(".png"));
	if (currentSrc.indexOf("_") > 0) {
		imageNameClean = imageNameClean.substring(0, currentSrc.indexOf("_"));
	}
	if (isOn) {
		document.getElementById(buttonId).src = imageNameClean + "_on.png";
	} else {
		document.getElementById(buttonId).src = imageNameClean + ".png";
	}
}
function showNormalMenuStyle(obj) {
	if (obj.isActiveMenuItem) {
		return;
	} else {
		obj.className='regularMenuItem';
	}
}
function showHoverMenuStyle(obj) {
	if (obj.isActiveMenuItem) {
		return;
	} else {
		obj.className='hoverMenuItem';
	}
}
function showSelectedMenuStyle(obj) {
	obj.className='selectedMenuItem';
}
oldActiveItem = null;
function makeActiveItem(newActiveItem) {
	if (oldActiveItem) {
		oldActiveItem.isActiveMenuItem = false;
		showNormalMenuStyle(oldActiveItem);
	}
	newActiveItem.isActiveMenuItem = true;
	oldActiveItem = newActiveItem;
	showSelectedMenuStyle(newActiveItem);
}
function menuItemClicked(menuItem) {
	makeActiveItem(menuItem);
	for (oneitem in MENU_ITEMS) {
		var obj = MENU_ITEMS[oneitem];
		if (obj[1] == menuItem.id) {
			document.location = '/'+obj[0];
		}
	}
}

function internalSendResetPasswordEmail(values, dialog, successFunc, errorFunc) {
	$.ajax({
		url: '/api/users/sendResetPasswordEmail',
		type: 'POST',
		dataType: 'json',
		data: values,
		success: function(response) {
			successFunc(dialog);
			showAlert(Text["messages.sendResetPasswordEmail.successHeader"], Text["messages.sendResetPasswordEmail.successMessage"]);
		},
		error: function(response) { 
			if (response.status == 404) {
				errorFunc(dialog, Text["messages.error.emailNotFound"]);
			} else {
				errorFunc(dialog, Text["messages.error.internalServerError"]);
			}
		}
	});
}

function internalChangePassword(values, dialog, successFunc, errorFunc) {
	$.ajax({
		url: '/api/users/changePassword',
		type: 'POST',
		dataType: 'json',
		data: values,
		success: function(response) {
			successFunc(dialog);
			showAlert(Text["messages.changePassword.successHeader"], Text["messages.changePassword.successMessage"]);
		},
		error: function(response) { 
			if (response.status == 404) {
				errorFunc(dialog, Text["messages.error.invalidCredentials"]);
			} else {
				errorFunc(dialog, Text["messages.error.internalServerError"]);
			}
		}
	});
}

function internalResetPassword(values, dialog, successFunc, errorFunc) {
	$.ajax({
		url: '/api/users/resetPassword',
		type: 'POST',
		dataType: 'json',
		data: values,
		success: function(response) {
			successFunc(dialog);
			showAlert(Text["messages.resetPassword.successHeader"], Text["messages.resetPassword.successMessage"]);
		},
		error: function(response) { 
			if (response.status == 404) {
				errorFunc(dialog, Text["messages.error.invalidKey"]);
			} else {
				errorFunc(dialog, Text["messages.error.internalServerError"]);
			}
		}
	});
}

function internalResendConfirmationEmail(values, dialog, successFunc, errorFunc) {
	$.ajax({
		url: '/api/users/resendConfirmationEmail',
		type: 'POST',
		dataType: 'json',
		data: values,
		success: function(response) {
			successFunc(dialog);
			showAlert(Text["messages.resendConfirmation.successHeader"], Text["messages.resendConfirmation.successMessage"]);
		},
		error: function(response) { 
			if (response.status == 404) {
				errorFunc(dialog, Text["messages.error.emailNotFound"]);
			} else
			if (response.status == 412) {
				errorFunc(dialog, Text["messages.error.resendConfirmation.emailAlreadyVerified"]);
			} else {
				errorFunc(dialog, Text["messages.error.internalServerError"]);
			}
		}
	});
}
function internalLogin(values, dialog, successFunc, errorFunc) {
	$.ajax({
		url: '/api/users/login',
		type: 'POST',
		dataType: 'json',
		data: values,
		success: function(response) {
			successFunc(dialog);
			userLoggedIn();
		},
		error: function(response) { 
			if (response.status == 403) {
				errorFunc(dialog, Text["messages.error.login.emailVerificationRequired"]);
			} else
			if (response.status == 404) {
				errorFunc(dialog, Text["messages.error.invalidCredentials"]);
			} else {
				errorFunc(dialog, Text["messages.error.internalServerError"]);
			}
		}
	});
}
function internalLogout() {
	$.ajax({
		url: '/api/users/logout',
		type: 'POST',
		dataType: 'json',
		data: {},
		success: function(response) {
			userLoggedOut();
		},
		error: function(response) {
			if (response.status == 404) {
				showAlert(Text["messages.logout.error.notLoggedIn.Header"], Text["messages.logout.error.notLoggedIn.Message"]);
			} else {
				showAlert(Text["messages.logout.error.unknown.Header"], Text["messages.logout.error.unknown.Message"]);
			}
			
		}
	});
}
function internalRegister(values, dialog, successFunc, errorFunc) {
	$.ajax({
		url: '/api/users/register',
		type: 'POST',
		dataType: 'json',
		data: values,
		success: function(response) { 
			successFunc(dialog);
			showAlert(Text["messages.registration.successHeader"], Text["messages.registration.successMessage"]);
		},
		error: function(response) { 
			if (response.status == 403) {
				errorFunc(dialog, Text["messages.error.registration.userExistsFailure"]);
			} else {
				errorFunc(dialog, Text["messages.error.internalServerError"]);
			}
		}
	});
}
function setVisibility(id, b) {
	$(id).css("visibility", b ? 'visible':'hidden');
}
function setDisplay(id, b) {
	$("#"+id).css("display", b ? 'inline':'none');
}

function contentLoading(flag) {
	setVisibility('div#contentLoadingOverlayWrapper', flag);	
}
function displayIssueMessage(flag) {
	setVisibility('div#issuesMessageOverlay', flag);	
}
var buttonsList = [];
function addButtonToButtonsList(button) {
	buttonsList.push(button);
}
function ActivateDialogButtons() {
	for (var i = 0; i < buttonsList.length; i++) {
		buttonsList[i].button( "option", "disabled", false );
	}
}
function dataLoadIssuesEncountered() {
	displayIssueMessage(true);
	contentLoading(true);
	setTimeout("internalTestServerStatus()", 5000);
}
function dataLoadedSuccessfully() {
	contentLoading(false);
	displayIssueMessage(false);
	fetchMessagePack();
}
function getCookie(name) {
	var cookies = document.cookie.split('; ');
	for (var i = 0, parts; (parts = cookies[i] && cookies[i].split('=')); i++) {
		if (parts[0] == name) return parts[1];
	}
	return null;
}
function setCookie(name, value) {
	document.cookie = name + "=" + value + "; path=/;";
}
function login(email, password) {
	internalLogin(email, password);
}
function setupDialogParams() {
	NAME_VALIDATION= {
			minSize:3,
			maxSize:60,
			regex: null, 
			message: null
	};
	EMAIL_VALIDATION= {
			minSize:7,
			maxSize:80,
	        // From jquery.validate.js (by joern), contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
			regex: /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i, 
			message: Text["messages.dialog.dialogInvalidEmailField"]
		};
	PASSWORD_VALIDATION= {
			minSize:7,
			maxSize:20,
			regex: /^(?=[^\d_].*?\d)\w(\w|[!@#$%]){6,20}/, 
			message:Text["messages.dialog.dialogInvalidPasswordField"]
		};
	
	registerDialogParams = {
			dialogName: Text["messages.dialog.registrationDialogHeader"],
			acceptButton: Text["messages.dialog.registrationDialogAcceptButton"],
			initialDialogMessage: Text["messages.dialog.registrationDialogInitialMessage"],
			links: 	[
			        ],
			fields: [
			         ["name", Text["dialog.dialogField_Name"], "text", NAME_VALIDATION, null],
			         ["email", Text["dialog.dialogField_Email"], "text", EMAIL_VALIDATION, null],
			         ["password", Text["dialog.dialogField_Password"], "password", PASSWORD_VALIDATION, null]
			        ],
	        acceptFunction: function (data, dialog, successFunc, errorFunc) {
	        	acceptRegister(data, dialog, successFunc, errorFunc);
	        }
		};
	changePasswordDialogParams = {
			dialogName: Text["messages.dialog.changePasswordDialogHeader"],
			acceptButton: Text["messages.dialog.changePasswordDialogAcceptButton"],
			initialDialogMessage: Text["messages.dialog.changePasswordDialogInitialMessage"],
	       	fields: [
	       	          ["email", Text["dialog.dialogField_Email"], "text", EMAIL_VALIDATION, null],
	       	          ["currentPassword", Text["dialog.dialogField_CurrentPassword"], "password", PASSWORD_VALIDATION, null],
	       	          ["newPassword", Text["dialog.dialogField_Password"], "password", PASSWORD_VALIDATION, null],
	       	          ["confirmPassword", Text["dialog.dialogField_ConfirmPassword"], "password", PASSWORD_VALIDATION, null]
	       	          ],
   	         acceptFunction: function (data, dialog, successFunc, errorFunc) {
   	        	acceptChangePassword(data, dialog, successFunc, errorFunc);
   	         }
	};
	resetPasswordDialogParams = {
			dialogName: Text["messages.dialog.resetPasswordDialogHeader"],
			acceptButton: Text["messages.dialog.resetPasswordDialogAcceptButton"],
			initialDialogMessage: Text["messages.dialog.resetPasswordDialogInitialMessage"],
			fields: [
			         ["email", Text["dialog.dialogField_Email"], "text", EMAIL_VALIDATION, null],
			         ["key", Text["dialog.dialogField_ValidationKey"], "password", null, null],
			         ["newPassword", Text["dialog.dialogField_Password"], "password", PASSWORD_VALIDATION, null],
			         ["confirmPassword", Text["dialog.dialogField_ConfirmPassword"], "password", PASSWORD_VALIDATION, null]
			         ],
			acceptFunction: function (data, dialog, successFunc, errorFunc) {
				acceptResetPassword(data, dialog, successFunc, errorFunc);
			}
	};
	loginDialogParams = {
			dialogName: Text["messages.dialog.loginDialogHeader"],
			acceptButton: Text["messages.dialog.loginDialogAcceptButton"],
			initialDialogMessage: Text["messages.dialog.loginDialogInitialMessage"],
			links: 	[
			       	 [Text["messages.dialog.resendConfirmationLink"], "", function (currentDialog) {showResendConfirmationDialog(currentDialog);}],
			       	 [Text["messages.dialog.sendResetPasswordEmailLink"], "", function (currentDialog) {showSendResetPasswordEmailDialog(currentDialog);}],
			        ],
			fields: [
			         ["email", Text["dialog.dialogField_Email"], "text", EMAIL_VALIDATION, null],
			         ["password", Text["dialog.dialogField_Password"], "password", PASSWORD_VALIDATION, null]
			        ],
			acceptFunction: function (data, dialog, successFunc, errorFunc) {
				acceptLogin(data, dialog, successFunc, errorFunc);
			}
	};
	resendConfirmationDialogParams = {
		dialogName: Text["messages.dialog.resendConfirmationDialogHeader"],
		acceptButton: Text["messages.dialog.resendConfirmationDialogAcceptButton"],
		initialDialogMessage: Text["messages.dialog.resendConfirmationDialogInitialMessage"],
   	 	fields: [
   	 	         ["email", Text["dialog.dialogField_Email"], "text", EMAIL_VALIDATION, null],
   	 	         ],
		acceptFunction: function (data, dialog, successFunc, errorFunc) {
			acceptResendConfirmation(data, dialog, successFunc, errorFunc);
		}
	};
	sendResetPasswordEmailDialogParams = {
		dialogName: Text["messages.dialog.sendResetPasswordEmailDialogHeader"],
		acceptButton: Text["messages.dialog.sendResetPasswordEmailDialogAcceptButton"],
		initialDialogMessage: Text["messages.dialog.sendResetPasswordEmailDialogInitialMessage"],
		fields: [
		         ["email", Text["dialog.dialogField_Email"], "text", EMAIL_VALIDATION, null],
		         ],
		acceptFunction: function (data, dialog, successFunc, errorFunc) {
			acceptSendResetPasswordEmail(data, dialog, successFunc, errorFunc);
		}
	};
}

function showResendConfirmationDialog(currentOpenDialog) {
	closeDialog($(currentOpenDialog));
	openFormDialog("resendConfirmation-dialog", resendConfirmationDialogParams);
}
function acceptResendConfirmation(values, dialog, successFunc, errorFunc) {
	internalResendConfirmationEmail(values, dialog, successFunc, errorFunc);
	return false;
}

function showSendResetPasswordEmailDialog(currentOpenDialog) {
	closeDialog($(currentOpenDialog));
	openFormDialog("sendResetPasswordEmail-dialog", sendResetPasswordEmailDialogParams);
}
function acceptSendResetPasswordEmail(values, dialog, successFunc, errorFunc) {
	internalSendResetPasswordEmail(values, dialog, successFunc, errorFunc);
	return false;
}

function showChangePasswordDialog() {
	openFormDialog("ChangePassword-dialog", changePasswordDialogParams);
}
function acceptChangePassword(values, dialog, successFunc, errorFunc) {
	internalChangePassword(values, dialog, successFunc, errorFunc);
	return false;
}

function showResetPasswordDialog(authenticationKey) {
	resetPasswordDialogParams.fields[1][4]=authenticationKey;
	openFormDialog("resetPassword-dialog", resetPasswordDialogParams);
}
function acceptChangePassword(values, dialog, successFunc, errorFunc) {
	internalChangePassword(values, dialog, successFunc, errorFunc);
	return false;
}

function acceptResetPassword(values, dialog, successFunc, errorFunc) {
	internalResetPassword(values, dialog, successFunc, errorFunc);
	return false;
}

function closeDialog(currentOpenDialog) {
	currentOpenDialog.dialog( "close" );
}

function loginButtonClicked() {
	if ($("#login").data("state")) {
		internalLogout();
	} else {
		openFormDialog("login-dialog", loginDialogParams);
	}
}
function acceptLogin(values, dialog, successFunc, errorFunc) {
	internalLogin(values, dialog, successFunc, errorFunc);
	return false;
}
function userLoggedIn() {
	setUserLoggedInState();
}
function userLoggedOut() {
	setUserLoggedOutState();
}
function setUserLoggedInState() {
	$("#login").button( "option", "label", Text["button.text.logout"]); 
	$("#login").data("state", true);	
}
function setUserLoggedOutState() {
	$("#login").button( "option", "label", Text["button.text.login"]);
	$("#login").data("state", false);	
}
function showRegister() {
	openFormDialog("register-dialog", registerDialogParams);
}
function acceptRegister(values, dialog, successFunc, errorFunc) {
	internalRegister(values, dialog, successFunc, errorFunc);
	return false;
}
function openFormDialog(dialogName, params) {
	var theDialog = $("#"+dialogName);
	var allFields = $( new Array() );
	var allLabels = $( new Array() );
	if (theDialog.length == 0) {
		theDialog = cloneObject("dialog-form-template", dialogName);
		for (i = 0; i < params.fields.length; i++) {
			labelClone = cloneSpecificObject(theDialog.find("#labelTemplate"), dialogName + "labelfield" + i); 
			if ("text" == params.fields[i][2]) {
				inputClone = cloneSpecificObject(theDialog.find("#inputTextTemplate"), dialogName + "inputfield" + i);
			} else
			if ("password" == params.fields[i][2]) {
				inputClone = cloneSpecificObject(theDialog.find("#inputPasswordTemplate"), dialogName + "inputfield" + i);
			}
			labelClone.attr("for", params.fields[i][0]);
			labelClone.text(params.fields[i][1]);
			inputClone.attr("name", params.fields[i][0]);
			inputClone.data("thedialog", theDialog);
			if (params.fields[i][4] != null) {
				inputClone.attr("value", params.fields[i][4]);
			}
			inputClone.data("validation", params.fields[i][3]);
			$(inputClone).keydown(function(event) {
				if (event.which == 13) {
					validate($($(this).data("thedialog")));
					event.preventDefault();
				}  
			});	
			allFields = allFields.add(inputClone );
			allLabels = allLabels.add(labelClone );
		}
		if (params.links != null) { 
			for (i = 0; i < params.links.length; i++) {
				var linkClone = cloneSpecificObject(theDialog.find("#dialogFormLinkTemplate"), dialogName + "_Link" + i);
				linkClone.attr("href", params.links[i][1]);
				linkClone.data("methodToCall", params.links[i][2]);
				linkClone.data("theDialog", theDialog);
				if (params.links[i][2] != null) {
					$(linkClone).click(function() {$(this).data("methodToCall")($(this).data("theDialog")); return false;});
				}
				linkClone.text(params.links[i][0]);
			}
		}
		theDialog.attr("title", params.dialogName);
		theDialog.find("#validateTips").text(params.initialDialogMessage);
		theDialog.find("#validateTips").data("initialMessage", params.initialDialogMessage);
		theDialog.find("#labelTemplate").remove();
		theDialog.find("#inputTextTemplate").remove();
		theDialog.find("#inputPasswordTemplate").remove();
		theDialog.find("#dialogFormLinkTemplate").remove();
		theDialog.css("display", "inline");
		theDialog.data("allFields", allFields);
		theDialog.data("allLabels", allLabels);
	}
	
	function updateTips( tips, message ) {
		tips
		.text( message )
		.addClass( "ui-state-highlight" );
		setTimeout(function() {
			tips.removeClass( "ui-state-highlight", 1500 );
		}, 500 );
	}
	function checkLength( o, fieldName, min, max, parentDialog) {
		if ( o.val().length > max || o.val().length < min ) {
			o.addClass( "ui-state-error" );
			var tip = Text["messages.dialog.dialogInvalidFieldLength"].replace("{1}", fieldName).replace("{2}", min).replace("{3}", max);
			var tips = parentDialog.find("#validateTips");
			updateTips( tips, tip);
			return false;
		} else {
			return true;
		}
	}
	function checkRegexp( o, regexp, message, parentDialog) {
		if ( !( regexp.test( o.val() ) ) ) {
			o.addClass( "ui-state-error" );
			var tips = parentDialog.find("#validateTips");
			updateTips( tips, message);
			return false;
		} else {
			return true;
		}
	}
	function validate(theDialog) {
        var bValid = true;
        var allFields = theDialog.data("allFields");
        var allLabels = theDialog.data("allLabels");
        allFields.removeClass( "ui-state-error" );
        for (i = 0; i < allFields.length; i++) {
        	var oneField = $(allFields[i]);
        	var oneLabel = $(allLabels[i]);
        	var validationObj = oneField.data("validation");
        	if (validationObj != null) {
	        	bValid = bValid && checkLength( oneField , oneLabel.text(), validationObj.minSize, validationObj.maxSize, theDialog);
	        	if (validationObj.regex != null) {
	        		bValid = bValid && checkRegexp( oneField,  validationObj.regex, validationObj.message, theDialog);
	        	}
        	}
        }
        if ( bValid ) {
        	var data = new Object();
        	for (i=0;i<allFields.length;i++) { 
        		var name	= allFields[i].name;
        		var value	= allFields[i].value;
        		data[name] = value;
    		}
        	var successFunc = function (dialog) {
        		dialog.dialog( "close" );
        	}
        	var errorFunc = function (dialog, message) {
    			var tips = dialog.find("#validateTips");
    			updateTips( tips, message);
        	}

        	var shouldClose = params.acceptFunction(data, theDialog, successFunc, errorFunc);
        	if (shouldClose) {
        		theDialog.dialog( "close" );
        	}
        }		
	}
	
    theDialog.dialog({
        autoOpen: true,
        height: 400,
        width: 450,
        modal: true,
        buttons: [
            {
            	text:params.acceptButton,
            	click:function() {
            		validate($(this));
	            }
            },
            {
            	text:Text["dialog.cancel"],
            	click: function() {
			                $( this ).dialog( "close" );
			            }
    		}
        ],
        close: function() {
            var allFields = $(this).data("allFields");
            allFields.val( "" ).removeClass( "ui-state-error" );
            var tips = $(this).find("#validateTips");
            tips.text(tips.data("initialMessage"));
        },
    });
}
function showAlert(dialogHeader, dialogMessage) {
	openMessageDialog("dialog-message", dialogHeader, dialogMessage);
}
function openMessageDialog(dialogName, dialogHeader, dialogMessage) {
	var theDialog = $("#"+dialogName);
	theDialog.attr("title", dialogHeader);
	theDialog.find("#dialogMessageMessage").text(dialogMessage);
	theDialog.css("display", "inline");
	theDialog.dialog({
        modal: true,
        buttons: [
              {	
            	text:Text["messages.dialog.messageDialogOkButton"],
              	click:function() {
          			$( this ).dialog( "close" );
          		}
              }
          ]
    });	
}

function cloneObject(templateName, cloneId) {
	var template = $('div#'+templateName);
	return cloneSpecificObject(template, cloneId);
}
function cloneSpecificObject(templateObj, cloneId) {
	var newObj = templateObj.clone();
	newObj.attr("id", cloneId);
	templateObj.parent().append(newObj);
	return newObj;
}
$(document).ready(function() {
	createDropDown();
	
	var $dropTrigger = $(".dropdown dt a");
	var $languageList = $(".dropdown dd ul");
	
	$dropTrigger.toggle(function() {
		$languageList.slideDown(200);
		$dropTrigger.addClass("active");
	}, function() {
		$languageList.slideUp(200);
		$(this).removeAttr("class");
	});

	$(document).bind('click', function(e) {
		var $clicked = $(e.target);
		if (! $clicked.parents().hasClass("dropdown"))
			$languageList.slideUp(200);
			$dropTrigger.removeAttr("class");
	});

	$(".dropdown dd ul li a").click(function() {
		var clickedValue = $(this).parent().attr("class");
		var clickedTitle = $(this).find("em").html();
		$("#target dt").removeClass().addClass(clickedValue);
		$("#target dt em").html(clickedTitle);
		$languageList.hide();
		$dropTrigger.removeAttr("class");
	});
});

function createDropDown(){
	var $form = $("div#country-select form");
	$form.hide();
	var source = $("#country-options");
	source.removeAttr("autocomplete");
	var selected = source.find("option:selected");
	var options = $("option", source);
	$("#country-select").append('<dl id="target" class="dropdown"></dl>')
	$("#target").append('<dt class="' + selected.val() + '"><a href="#"><span class="flag"></span><em>' + selected.text() + '</em></a></dt>')
	$("#target").append('<dd><ul></ul></dd>')
	options.each(function(){
		$("#target dd ul").append('<li class="' + $(this).val() + '"><a href="' + $(this).attr("title") + '"><span class="flag"></span><em>' + $(this).text() + '</em></a></li>');
		});
}
function getRandomCSRFToken() {
	return Math.random();
}
/////////////////////////////////////////
// Math.random replacement for improved unpredictable randomness
/////////////////////////////////////////
//LICENSE (BSD):
//
// Copyright 2010 David Bau, all rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// 
//   1. Redistributions of source code must retain the above copyright
//      notice, this list of conditions and the following disclaimer.
//
//   2. Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
// 
//   3. Neither the name of this module nor the names of its contributors may
//      be used to endorse or promote products derived from this software
//      without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//seedrandom.js version 2.0.
//Author: David Bau 4/2/2011
//
//Defines a method Math.seedrandom() that, when called, substitutes
//an explicitly seeded RC4-based algorithm for Math.random().  Also
//supports automatic seeding from local or network sources of entropy.
(function(j,i,g,m,k,n,o){function q(b){var e,f,a=this,c=b.length,d=0,h=a.i=a.j=a.m=0;a.S=[];a.c=[];for(c||(b=[c++]);d<g;)a.S[d]=d++;for(d=0;d<g;d++)e=a.S[d],h=h+e+b[d%c]&g-1,f=a.S[h],a.S[d]=f,a.S[h]=e;a.g=function(b){var c=a.S,d=a.i+1&g-1,e=c[d],f=a.j+e&g-1,h=c[f];c[d]=h;c[f]=e;for(var i=c[e+h&g-1];--b;)d=d+1&g-1,e=c[d],f=f+e&g-1,h=c[f],c[d]=h,c[f]=e,i=i*g+c[e+h&g-1];a.i=d;a.j=f;return i};a.g(g)}function p(b,e,f,a,c){f=[];c=typeof b;if(e&&c=="object")for(a in b)if(a.indexOf("S")<5)try{f.push(p(b[a],e-1))}catch(d){}return f.length?f:b+(c!="string"?"\0":"")}function l(b,e,f,a){b+="";for(a=f=0;a<b.length;a++){var c=e,d=a&g-1,h=(f^=e[a&g-1]*19)+b.charCodeAt(a);c[d]=h&g-1}b="";for(a in e)b+=String.fromCharCode(e[a]);return b}i.seedrandom=function(b,e){var f=[],a;b=l(p(e?[b,j]:arguments.length?b:[(new Date).getTime(),j,window],3),f);a=new q(f);l(a.S,j);i.random=function(){for(var c=a.g(m),d=o,b=0;c<k;)c=(c+b)*g,d*=g,b=a.g(1);for(;c>=n;)c/=2,d/=2,b>>>=1;return(c+b)/d};return b};o=i.pow(g,m);k=i.pow(2,k);n=k*2;l(i.random(),j)})([],Math,256,6,52);
Math.seedrandom(Constants.SERVER_RANDOM_SEED,true);